package team.se.tms.shiro;


import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import team.se.tms.constant.SessionConstant;
import team.se.tms.dto.RoleDetail;
import team.se.tms.po.AuthorityInfo;
import team.se.tms.po.UserInfo;
import team.se.tms.service.RoleInfoService;
import team.se.tms.service.UserInfoService;
import team.se.tms.util.Jurisdiction;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
 * 权限管理类
 *
 * @author winkyle
 * @date 2018/11/8
 */
@Slf4j
public class ShiroRealm extends AuthorizingRealm {
	@Autowired
	private UserInfoService userInfoService;

	@Autowired
	private RoleInfoService roleInfoService;
	/**
	 * 认证：登录认证
	 *
	 * @param token 令牌
	 * @return AuthenticationInfo 认证信息
	 * @throws AuthenticationException 认证异常
	 * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
	 * @create on 2018/11/17 by winkyle
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String account = (String)token.getPrincipal();
		UserInfo userInfo = null;
		try {
			userInfo = userInfoService.getUserInfo(account);
		} catch (Exception e) {
			e.printStackTrace();
			throw new AuthenticationException();
		}
		if(userInfo == null){
			throw new UnknownAccountException();
		}
		Jurisdiction.getSession().setAttribute(SessionConstant.USER,userInfo);
		//TODO FHLOG.save(USERNAME, "登录系统"); 存储一下日志操作记录
		log.debug("登录帐号:{}，用户id:{}，密码{}",account, userInfo.getUserId(), userInfo.getUserPassword());
		return new SimpleAuthenticationInfo(userInfo.getUserId(), userInfo.getUserPassword(), getName());
	}


	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法(non-Javadoc)
	 *
	 * @param principals 用来获取登录者
	 * @return AuthorizationInfo 授权信息
	 * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		String userId = (String) principals.getPrimaryPrincipal();
		RoleDetail roleDetail = null;
		try {
			roleDetail = roleInfoService.getRoleDetail(userId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new AuthenticationException();
		}
		if(roleDetail != null) {
			authorizationInfo.addRole(roleDetail.getRoleId());
			List<AuthorityInfo> authorityInfos = roleDetail.getAuthorityInfos();
			Set<String> permissionNames = new HashSet<String>();
			if(authorityInfos != null) {
				for (AuthorityInfo authorityInfo : authorityInfos) {
					permissionNames.add(authorityInfo.getAuthorityId());
				}
			}
			authorizationInfo.setStringPermissions(permissionNames);
		}
		log.debug("{}进入了授权",userId);
		return authorizationInfo;
	}

}
